import { assertExists } from '@notes/global/utils';
import type { BaseBlockModel, Page } from '@notes/store';

import type {
    DataViewDataType,
    DataViewTypes,
} from '../../../database-block/common/data-view.js';
import type {
    Cell,
    Column,
    DatabaseBlockModel,
} from '../../../database-block/index.js';
import type { BlockModels, SerializedBlock } from '../../utils/index.js';
import { BaseService } from '../service.js';

export class LegacyDatabaseBlockService extends BaseService<DatabaseBlockModel> {
    initDatabaseBlock(
        page: Page,
        model: BaseBlockModel,
        databaseId: string,
        viewType: DataViewTypes,
        isAppendNewRow = true
    ) {
        const blockModel = page.getBlockById(databaseId) as DatabaseBlockModel;
        assertExists(blockModel);
        blockModel.initTemplate(viewType);
        if (isAppendNewRow) {
            // Add a paragraph after database
            const parent = page.getParent(model);
            assertExists(parent);
            page.addBlock('affine:paragraph', {}, parent.id);
        }
        blockModel.applyColumnUpdate();
    }

    override block2Json(
        block: BlockModels['affine:database'],
        children: SerializedBlock[]
    ): SerializedBlock {
        const columns = [...block.columns];
        const rowIds = block.children.map(child => child.id);
        return {
            flavour: block.flavour,
            databaseProps: {
                id: block.id,
                title: block.title.toString(),
                rowIds,
                cells: block.cells,
                columns,
                views: block.views,
            },
            children,
        };
    }

    override async onBlockPasted(
        model: BlockModels['affine:database'],
        props: {
            rowIds: string[];
            columns: Column[];
            cells: Record<string, Record<string, Cell>>;
            views: DataViewDataType[];
        }
    ) {
        const { rowIds, columns, cells } = props;
        const columnIds = columns.map(column => column.id);
        model.deleteColumn(model.id);
        const newColumnIds = columns.map(schema => model.addColumn('end', schema));
        model.applyColumnUpdate();

        const newRowIds = model.children.map(child => child.id);
        rowIds.forEach((rowId, rowIndex) => {
            const newRowId = newRowIds[rowIndex];
            columnIds.forEach((columnId, columnIndex) => {
                const cellData = cells[rowId]?.[columnId];
                const value = cellData?.value;
                if (!value) return;
                model.updateCell(newRowId, {
                    columnId: newColumnIds[columnIndex],
                    value,
                });
            });
        });
    }
}
